<template>
  <q-page class="cc-admin column q-pa-sm">
    <div>
      <q-table color="primary" class="cross_table" flat separator="cell" :columns="columns" :data="menuList" row-key="id" @request="query" hide-bottom :rows-per-page-options="[0]">
        <template v-slot:top>
          <div class="row no-wrap full-width">
            <q-input clearable outlined dense placeholder="请输入关键字搜索" class="on-left" @input="query" debounce="500" v-model="key">
              <template #append>
                <q-btn flat round icon="search" color="primary" @click="query" :loading="loading">
                  <q-tooltip>搜索</q-tooltip>
                </q-btn>
              </template>
            </q-input>
            <q-space />
            <div class="q-gutter-xs">
              <q-btn icon="add" no-wrap color="primary" label="新建" @click="add" />
            </div>
          </div>
        </template>

        <template v-slot:header="props">
          <q-tr>
            <q-th v-for="col in props.cols" :key="col.name" :props="props">{{ col.label }}</q-th>
          </q-tr>
        </template>
        <template #body="props">
          <menu-item :menu="props.row" :props="props" @edit="edit" @addChild="addChild" @del="del" @toggleExpand="toggleExpand" />
        </template>
      </q-table>
    </div>

    <q-dialog :maximized="maximized" flat persistent ref="dialog">
      <q-form @submit="submit" :class="dialogSize">
        <h5 class="view_title justify-between q-px-md">
          {{ editType }}{{ getDictLabel(menuType, form.menuType) }}
          <q-btn dense outline round icon="clear" size="sm" v-close-popup />
        </h5>
        <q-scroll-area class="col">
          <div class="row q-col-gutter-x-md dialog_form q-pa-md">
            <div class="col-6">
              <h5>
                <q-icon name="star" color="red" />
                {{ form.menuType === 2 ? '按钮/权限' : '菜单' }}名称：
              </h5>
              <q-input outlined dense v-model="form.name" :rules="[requiredTest]" />
            </div>
            <div class="col-6" v-if="form.menuType === 0" key="0">
              <h5>
                子系统：
              </h5>
              <q-select dense outlined options-dense v-model="form.subSystem" clearable option-label="name" option-value="id" :options="subSystemOptions" emit-value map-options @input="subSystemInput(form.subSystem, form)" />
            </div>
            <div class="col-6" v-if="form.menuType !== 0" key="0">
              <h5>
                <q-icon name="star" color="red" />上级菜单：
              </h5>
              <q-field outlined dense v-model="form.parentId" class="cursor-pointer" :rules="[requiredTest]">
                <template #control>{{ parent.name }}</template>
                <q-menu ref="qMenu" fit>
                  <div class="q-pa-md q-gutter-sm">
                    <q-input outlined dense v-model="filter" ref="filter">
                      <template v-slot:append>
                        <q-icon v-if="filter !== ''" name="clear" class="cursor-pointer" @click="resetFilter" />
                      </template>
                    </q-input>

                    <q-tree ref="qTree" :nodes="list" node-key="id" label-key="name" :filter="filter" :filter-method="filterTreeNodes" default-expand-all :selected.sync="selectParentKey" @update:selected="selectParent" />
                  </div>
                </q-menu>
              </q-field>
            </div>
            <div class="col-3" v-if="form.menuType !== 2" key="1">
              <h5>菜单图标：</h5>
              <q-input outlined dense v-model="form.icon">
                <template #prepend>
                  <q-icon size="sm" :name="form.icon" :color="form.iconColor ? form.iconColor : 't-grey'" />
                </template>
                <template #append>
                  <q-btn round dense flat icon="search" color="primary">
                    <q-menu>
                      <q-btn round dense flat v-for="v in icons" :key="v" :icon="v" color="t-grey" @click="form.icon = v" />
                    </q-menu>
                  </q-btn>
                </template>
              </q-input>
            </div>
            <div class="col-3">
              <h5>图标颜色：</h5>

              <q-select dense outlined options-dense ref="colorSelect" v-model="form.iconColor" :options="colorOptions" emit-value map-options>
                <template v-slot:option="option">
                  <q-item clickable v-ripple :class="'bg-' + option.opt.value" @click="selectColor(option.opt.value)">
                    <q-item-section></q-item-section>
                  </q-item>
                </template>
              </q-select>
            </div>
            <template v-if="form.menuType !== 2">
              <div class="col-6">
                <h5>
                  <q-icon name="star" color="red" />访问地址：
                </h5>
                <q-input outlined dense v-model="form.url" :rules="[requiredTest]" />
              </div>
              <div class="col-6">
                <h5>
                  <q-icon name="star" color="red" />组件位置：
                </h5>
                <q-input outlined dense v-model="form.component" :rules="[requiredTest]" />
              </div>
              <div class="col-6">
                <h5>
                  app组件位置：
                </h5>
                <q-input outlined dense v-model="form.appComponent" />
              </div>
              <div class="col-6">
                <h5>默认跳转：</h5>
                <q-input outlined dense v-model="form.redirect" />
              </div>
              <div class="col-6">
                <h5>菜单排序：</h5>
                <q-input outlined dense v-model="form.sortNo" type="number" />
              </div>
              <div class="col-6">
                <h5>
                  统计接口：
                </h5>
                <q-input outlined dense v-model="form.statUrl" />
              </div>
              <div class="col-6">
                <h5>
                  统计数量：
                </h5>
                <q-input outlined dense v-model="form.numder" />
              </div>
              <div class="col-6" v-if="form.menuType === 1">
                <h5>
                  所属系统：
                </h5>
                <q-input disable outlined dense v-model="form.owningSystem" />
              </div>
              <div class="col-3">
                <h5>
                  <q-icon name="star" color="red" />是否路由菜单：
                </h5>
                <q-btn-toggle class="q_b_toggle" v-model="form.route" :options="[{ label: '路由', value: true }, { label: '不路由', value: false }]" />
              </div>
              <div class="col-3">
                <h5>
                  <q-icon name="star" color="red" />打开方式：
                </h5>
                <q-btn-toggle class="q_b_toggle" v-model="form.internalOrExternal" :options="[{ label: '内部', value: false }, { label: '外部', value: true }]" />
              </div>
            </template>
            <div class="col-12 row q-col-gutter-x-md">
              <div class="col-3">
                <h5>
                  <q-icon name="star" color="red" />电脑端菜单：
                </h5>
                <q-btn-toggle class="q_b_toggle" v-model="form.showPc" :options="[{ label: '显示', value: true }, { label: '隐藏', value: false }]" />
              </div>
              <div class="col-3">
                <h5>
                  <q-icon name="star" color="red" />手机端菜单：
                </h5>
                <q-btn-toggle class="q_b_toggle" v-model="form.showPhone" :options="[{ label: '显示', value: true }, { label: '隐藏', value: false }]" />
              </div>
              <div class="col-3">
                <h5>
                  <q-icon name="star" color="red" />全屏布局：
                </h5>
                <q-btn-toggle class="q_b_toggle" v-model="form.fullLayout" :options="[{ label: '否', value: false }, { label: '是', value: true }]" />
              </div>
            </div>
            <div class="col-6" v-if="form.menuType === 2" key="2">
              <h5>
                <q-icon name="star" color="red" />授权标识：
              </h5>
              <q-input outlined dense v-model="form.perms" :rules="[requiredTest]">
                <template v-slot:hint>动态表单编号:add/edit/delete</template>
              </q-input>
            </div>
          </div>
        </q-scroll-area>
        <div class="row justify-center q-pa-md">
          <q-btn outline color="primary" icon="mdi-close-thick" label="关闭" v-close-popup />
          <q-btn class="q-mx-sm" color="primary" icon="mdi-check-bold" label="提交" type="submit" />
        </div>
      </q-form>
    </q-dialog>
  </q-page>
</template>

<script>
import { requiredTest } from 'boot/inputTest';
import { colorOptions } from 'boot/datatype';
import { getter, formatter, getDictLabel } from 'boot/dictionary';
import menuItem from './item';

export default {
  name: 'SysMenu',
  mixins: [],
  components: {
    menuItem,
  },
  data() {
    return {
      filter: null,
      ticked: [],
      QueryTreeList: [],
      colorOptions,
      mobile: false,
      maximized: false,
      dialogSize: 'dialog_card column',
      loading: false,
      editType: '',
      key: '',
      form: {},
      columns: [
        {
          name: 'index',
          align: 'center',
          label: '展开/收缩',
          field: 'index',
          headerClasses: 'cc-table-index',
        },
        {
          name: 'name',
          align: 'left',
          label: '菜单名称',
          field: 'name',
        },
        {
          name: 'icon',
          align: 'center',
          label: '图标',
          field: 'icon',
        },
        {
          name: 'menuType',
          align: 'left',
          label: '菜单类型',
          field: 'menuType',
        },
        {
          name: 'url', align: 'center', label: '访问地址', field: 'url',
        },
        {
          name: 'showPc',
          align: 'center',
          label: '电脑端',
          field: 'showPc',
        },
        {
          name: 'showPhone',
          align: 'center',
          label: '手机端',
          field: 'showPhone',
        },
        {
          name: 'sortNo',
          align: 'center',
          label: '菜单排序',
          field: 'sortNo',
        },
        {
          name: 'opt',
          align: 'center',
          label: '操作',
          field: 'opt',
        },
      ],
      parent: {},
      menuType: formatter('menuType'),
      list: [],
      // 之前的菜单列表，主要用来还原状态
      orginMenuList: [],
      shipTypeOptions: [],
      shipType: '',
      menuList: [],
      icons: getter('icon'),
      subSystemOptions: [],
      url: {
        list: '/sys/permission/list',
        add: '/sys/permission/add',
        edit: '/sys/permission/edit',
        delete: '/sys/permission/delete',
        deleteBatch: '/sys/permission/deleteBatch',
        exportXlsUrl: '/sys/permission/exportXls',
        importExcelUrl: '/sys/permission/importExcel',
      },
      selectParentKey: null,
    };
  },
  methods: {
    requiredTest,
    getDictLabel,
    filterTreeNodes(node, filter) {
      return node.name && node.name.indexOf(filter) > -1;
    },

    resetFilter() {
      this.filter = '';
      this.$refs.filter.focus();
    },
    selectParent(key) {
      const node = this.$refs.qTree.getNodeByKey(key);
      this.form.parentId = node.id;
      this.parent.name = node.name;
      this.$refs.qMenu.hide();
    },
    selectColor(iconColor) {
      this.$set(this.form, 'iconColor', iconColor);
      this.$refs.colorSelect.hidePopup();
    },
    edit(p) {
      if (this.editBefore(p)) {
        this.editType = '编辑';
        this.form = {
          ...p,
        };
        this.$refs.dialog.show();
      }
      this.editAfter();
    },
    editAfter() {

    },
    toggleExpand(menu) {
      // 正常操作，展开只展开本级，收缩则收缩所有下级
      const expand = !menu.expand;
      this.menuList.forEach((m) => {
        if (m.id === menu.id) {
          m.expand = expand;
        }
        // 找到子节点
        if (m.parentId === menu.id) {
          m.parent.expand = expand;
          if (expand) {
            this.expandAllSon(menu.id);
          }
          // 折叠的话需要把所有后代后收缩起来
          if (!expand) {
            this.folderAllSon(menu.id);
          }
        }
      });
    },
    expandAllSon(id) {
      // 展开所有子节点
      this.menuList.forEach((m) => {
        if (m.parentId === id) {
          m.parent.expand = true;
          m.expand = true;
          this.expandAllSon(m.id);
        }
      });
    },
    folderAllSon(id) {
      this.menuList.forEach((m) => {
        if (m.parentId === id) {
          m.parent.expand = false;
          this.folderAllSon(m.id);
        }
      });
    },
    query() {
      this.loading = true;
      const url = this.key ? `${this.url.list}?key=${this.key}` : this.url.list;
      this.$axios.get(url).then((r) => {
        this.orginMenuList = this.menuList;
        this.menuList = [];
        this.list = r.result;
        this.initMenuList(this.list, 1, { expand: true });
      }).finally(() => {
        this.loading = false;
      });
    },
    // parent是否展开决定了子节点是否显示
    initMenuList(list, level, parent) {
      list.forEach((m) => {
        // 尝试还原下原来的状态
        const orgin = this.orginMenuList.find((o) => m.id === o.id);
        const expand = orgin && orgin.expand;
        this.menuList.push({
          ...m, level, expand, parent,
        });
        if (m.children && m.children.length > 0) {
          this.initMenuList(m.children, level + 1, { expand });
        }
      });
    },
    reset() {
      this.form = {
        id: '',
        title: '',
        parentId: '',
        icon: '',
        iconColor: '',
        component: '',
        appComponent: '',
        url: '',
        numder: '',
        statUrl: '',
        redirect: '',
        sortNo: 100,
        menuType: 0,
        route: true,
        showPc: true,
        showPhone: true,
        fullLayout: false,
        perms: '',
        status: '1',
        internalOrExternal: false,
      };
    },
    add() {
      this.editType = '新建';
      this.reset();
      this.$refs.dialog.show();
    },
    addChild(p, menuType = 1) {
      this.editType = '新建';
      this.reset();
      this.parent = p;
      this.form.parentId = p.id;
      this.form.menuType = menuType;
      this.form.owningSystem = p.owningSystem;
      this.$refs.dialog.show();
    },
    subSystemInput(v, row) {
      const opt = this.subSystemOptions.find((o) => o.id === v);
      if (opt) {
        this.form.owningSystem = opt.code;
      }
    },

    getMenuById(menuList, id) {
      // 根据Id把parent找出来
      menuList.forEach((menu) => {
        if (menu.id === id) {
          this.parent = menu;
        }
        if (menu.children && menu.children.length > 0) {
          this.getMenuById(menu.children, id);
        }
      });
    },
    editBefore(row) {
      this.getMenuById(this.list, row.parentId);
      return true;
    },
    submit() {
      const url = this.editType === '新建' ? this.url.add : this.url.edit;
      this.loading = true;
      this.$axios.post(url, this.form).then(({ message }) => {
        this.$info(message);
      }).finally(() => {
        this.$refs.dialog.hide();
        this.query();
      });
    },
    del({ id }) {
      this.loading = true;
      return this.$axios.delete(this.url.delete, { params: { id } }).then((r) => {
        this.$info(r.message);
      }).finally(() => {
        this.query();
      });
    },
  },
  mounted() {
    this.mobile = this.$q.platform.is.mobile;
    if (this.mobile) {
      this.dialogSize = 'dialog_full column';
      this.maximized = true;
    } else {
      this.dialogSize = 'dialog_card column';
      this.maximized = false;
    }
    this.$axios.get('/sys/subsystem/list?pageSize=50').then((r) => {
      this.subSystemOptions = r.result.records;
    });
    this.$axios.get('/sys/role/queryTreeSmsList').then((res) => {
      if (res.success) {
        this.QueryTreeList = res.result.treeList;
      }
    });

    this.query();
  },
};
</script>

<style lang="stylus">
.cell-width
  max-width 200px
</style>
